package semanticAbstraction.wsmxAdapter.wsmlHelper;

import helper.GroundingInformation;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Set;

import org.deri.wsmo4j.io.parser.wsml.ParserImpl;
import org.deri.wsmo4j.io.serializer.wsml.SerializerImpl;
import org.omwg.ontology.Ontology;
import org.wsmo.common.IRI;
import org.wsmo.common.TopEntity;
import org.wsmo.common.exception.InvalidModelException;
import org.wsmo.factory.Factory;
import org.wsmo.factory.WsmoFactory;
import org.wsmo.service.Goal;
import org.wsmo.service.Interface;
import org.wsmo.service.WebService;

// bad one: org.wsmo.service.Choreography
import org.wsmo.service.choreography.Choreography;
import org.wsmo.service.signature.Grounding;
import org.wsmo.service.signature.In;
import org.wsmo.service.signature.NotGroundedException;
import org.wsmo.service.signature.StateSignature;
import org.wsmo.service.signature.WSDLGrounding;
import org.wsmo.wsml.Parser;
import org.wsmo.wsml.ParserException;
import org.wsmo.wsml.Serializer;


public class WSMOHelper {
	public static WsmoFactory wsmoFactory = Factory.createWsmoFactory(null);
	//private static Parser parser = Factory.createParser(new HashMap<String, Object>());
	public static Parser parser = new ParserImpl(new HashMap<String, Object>());
	//private static Serializer serializer = Factory.createSerializer(new HashMap<String, Object>());
	public static Serializer serializer = new SerializerImpl(new HashMap<String, Object>());
	
	
	public static String mergeGoalWithInstances1(String goalDoc, String instanceDoc) throws ParserException, InvalidModelException{
		TopEntity goalTe;
		TopEntity ontologyTe;
		
		goalTe=parseGoal(goalDoc);
		ontologyTe=parseOntology(instanceDoc);
		

		
		TopEntity[] mergedTes;
		
		
		mergedTes=new TopEntity[2];
		
		mergedTes[0]=goalTe;
		mergedTes[1]=ontologyTe;       
		
		StringBuffer strBuf;
		
		strBuf=new StringBuffer();
		
		serializer.serialize(mergedTes, strBuf);
		
		String result;
		
		result = strBuf.toString();
		
		return result;
		
	}
	
	
	public static String mergeGoalWithInstances2(String goalDoc, String instanceDoc) throws ParserException, InvalidModelException{
		TopEntity[] goalTes;
		TopEntity[] ontologyTes;
		
		goalTes=parseTopEntities(goalDoc);
		ontologyTes=parseTopEntities(instanceDoc);
		

		
		TopEntity[] mergedTes;
		
		
		ArrayList<TopEntity> mergedList = new ArrayList<TopEntity>();
		
		int mergedLength=goalTes.length+ontologyTes.length;
		
		mergedTes=new TopEntity[mergedLength];
		
		for(TopEntity te:goalTes){
			mergedList.add(te);
			
			if(te instanceof Interface){
				Interface itf = (Interface)te;
			
				itf.getChoreography();
			}
			
			//System.out.println(te.getIdentifier().toString());
			
		}
		
		for(TopEntity te:ontologyTes){
			mergedList.add(te);
		}
		
		/*
		for(int i=0;i<goalTes.length;i++){
			mergedList.add(arg0)
			System.out.println(mergedTes[i]);
		}
		
		for(int i=goalTes.length;i<mergedLength;i++){
			mergedTes[i]=ontologyTes[i-goalTes.length];
		}
		*/
		
		mergedTes=mergedList.toArray(new TopEntity[0]);
		  
		
		StringBuffer strBuf;
		
		strBuf=new StringBuffer();
		
		serializer.serialize(mergedTes, strBuf);
		
		String result;
		
		result = strBuf.toString();
		
		
		return result;
		
	}
	
	
	public static String mergeGoalWithInstances(String goalDoc, String instanceDoc){
		
		String merged = goalDoc + "\n" + instanceDoc.substring(instanceDoc.indexOf("ontology")); 
		
		
		return merged;
	}
	
	
	public static void test(){
		Parser parser = new ParserImpl(null);
	}
	
	public static String serializeOntology(Ontology ontology){
		StringBuffer strBuf=new StringBuffer();
		Ontology[] array=new Ontology[1];
		array[0]=ontology;
		serializer.serialize(array, strBuf);
		
		return strBuf.toString();
	}
	
	
	public static Goal parseGoal(String goalStr) throws ParserException, InvalidModelException{
	
		TopEntity[] tes;
		
		tes=parseTopEntities(goalStr);
		
		Goal goal=null;
		
		for(TopEntity te : tes){
			if(te instanceof Goal){
				goal = (Goal)te;
				break;
			}
		}
		
		if(goal==null){
			throw new InvalidModelException("No goals in String!");
		}
		
		return goal;
		
	}
	
	public static WebService parseWebService(String webServiceStr) throws ParserException, InvalidModelException{
		
		TopEntity[] tes;
		
		tes=parseTopEntities(webServiceStr);
		
		WebService ws=null;
		
		for(TopEntity te : tes){
			System.out.println("Found: "+te.getIdentifier().toString());
			
			if(te instanceof WebService){
				ws = (WebService)te;
				break;
			}
			
		}
		
		if(ws==null){
			throw new InvalidModelException("No Web Service in String!");
		}
		
		return ws;
		
	}
	
	
	public static Ontology parseOntology(String ontologyStr) throws ParserException, InvalidModelException{
		
		TopEntity[] tes;
		
		tes=parseTopEntities(ontologyStr);
		
		Ontology ont=null;
		
		for(TopEntity te : tes){
			if(te instanceof Ontology){
				ont = (Ontology)te;
				break;
			}
			
		}
		
		if(ont==null){
			throw new InvalidModelException("No ontology in String!");
		}
		
		return ont;
		
	}
	

	
	public static TopEntity[] parseTopEntities(String wsmlDoc) throws ParserException, InvalidModelException{
		StringBuffer strBuf = new StringBuffer(wsmlDoc);
		TopEntity[] tes;
		
		System.out.println("before PARSE: \n"+strBuf.toString()+"\n  ^^^^^^^^^^^^^^^ ");
		
		
		tes=parser.parse(strBuf);
		return tes;
	}
	
	
	

	public static GroundingInformation getWSDLLocation(WebService ws){
		Set<Interface> itfs;
		itfs=ws.listInterfaces();
	
		
		Choreography choreo;
		StateSignature stateSig;
		Set<In> inModes;
		Set<Grounding> grnds;
		WSDLGrounding wgrnd;
		IRI iri;
		
		String returnValue="";
		GroundingInformation grounding=new GroundingInformation();
		
loop1:	for(Interface itf:itfs){
			
			
			choreo=(Choreography)itf.getChoreography();
			
			stateSig=choreo.getStateSignature();
			
			inModes=stateSig.listInModes();
			
			
			for(In inMode:inModes){
				try {
					grnds=inMode.getGrounding();
					
					for(Grounding grnd:grnds){
						
						wgrnd=(WSDLGrounding)grnd;
						iri=wgrnd.getIRI();
					
						
						grounding.setWsdlLocation(getWSDLLocationFromIRI(iri));
						grounding.setPort(getPort(iri));
						grounding.setOperation(getOperation(iri));
						
						
						
						break loop1;
					}
					
				} catch (NotGroundedException e) {
					System.out.println("not grounded");
				}
			}
			
			
		}
		
		return grounding;
	
	}
	
	private static String getWSDLLocationFromIRI(IRI iri){
		String str="";
		int index;
		str=iri.toString();
		
		index=str.indexOf(iri.getLocalName());
		
		return str.substring(0, index-1);
		
	}
	
	private static String getPort(IRI iri){
		//wsdl.interfaceMessageReference(myservice/myoperation/in0)
		String localName;
		String port;
		
		localName=iri.getLocalName();
		
		int brackOpenIdx;
		int firstSlashIdx;
		
		brackOpenIdx=localName.indexOf("(");
		firstSlashIdx=localName.indexOf("/");
		
		
		port=localName.substring(brackOpenIdx+1, firstSlashIdx);
		
		System.out.println(port);
		
		return port;
	}
	
	private static String getOperation(IRI iri){
		//wsdl.interfaceMessageReference(myservice/myoperation/in0)
		String localName;
		String operation;
		
		localName=iri.getLocalName();
		
		int firstSlashIdx;
		int secondSlashIdx;
		
		firstSlashIdx=localName.indexOf("/");
		secondSlashIdx=localName.indexOf("/", firstSlashIdx+1);
		
		
		operation=localName.substring(firstSlashIdx+1, secondSlashIdx);
		
		System.out.println(operation);
		
		return operation;
	}
	
	public static String getRightmostPartOfNamespace(String namespaceStr){
		int index=namespaceStr.lastIndexOf("/");
		
		return namespaceStr.substring(index+1).replace("#", "");
		
		
	}
	
	
}
